#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <array>
#include <fstream>
#include <sstream>
#include <iostream>
#include <string.h>
#include "data.h"

using namespace std;

crailway::crailway(){
	printf("\n");
}

crailway::~crailway(){
	//delete all object trains*
	train_iterator tr = m_trainset.begin();
	while(tr != m_trainset.end()){

		printf("remove %d train\n", tr->first);
		delete(tr->second);
		tr++;
	}
}

void crailway::addtrainconfig(int train_id, station & _station){

	ctrain * train;
	train_iterator tr_it = m_trainset.find(train_id);
	if(tr_it != m_trainset.end()){
		//The train already exists so add the station (next)
		train = tr_it->second;
	}else{
	    //Create a new object train
		train = new ctrain(train_id);
		train_pair pr(train_id,train);
		m_trainset.insert(pr);
	}

	train->add_station(_station);
}

void crailway::set_route_map(string & line){

	station stations_source;
	station station_dest;
	int route_lenght;
	
	char buffer[20]="";
	int index1 = line.find(":");
	int index2 = line.find(";");
	int index3 = line.find(";", index2 + 1);
	line.copy(buffer, index2 - index1 - 1,  index1 + 1); 
	stations_source.id = atoi(buffer);
	stations_source.id--;
	memset(buffer, 0, 20);
	line.copy(buffer, index3 - index2 - 1,  index2 + 1); 
	route_lenght = atoi(buffer);
	memset(buffer, 0, 20);
	line.copy(buffer, line.length() - index3 - 1,  index3 + 1);
	station_dest.id = atoi(buffer);
	station_dest.id--;
	
	connection conn(stations_source, station_dest);
	m_routeplan.loadconfiguration(conn, route_lenght);
}

void crailway::set_train_plan(string & line){
	//id train is starting from 1
	//so we have make - 1
	int train_no;
	station _station;
	char buffer[20]="";
	int index1 = line.find(":");
	int index2 = line.find(";");
	line.copy(buffer, index2 - index1 - 1,  index1 + 1);
	train_no = atoi(buffer);
	//Load the route plan
	train_no--;
	while((index1 = line.find(",",index2 + 1)) != line.npos )
	{
		memset(buffer, 0, 20);
		line.copy(buffer, index1 - index2 - 1,  index2 + 1);
		_station.id =  atoi(buffer);
		_station.id--;
		index2 = index1;
		addtrainconfig(train_no,_station);
	}
	memset(buffer, 0, 20);
	line.copy(buffer, line.length() - index2 - 1,  index2 + 1);
	_station.id =  atoi(buffer);
	_station.id--;
	addtrainconfig(train_no,_station);
}

void crailway::loadconfiguration(char * filename){

	ifstream input(filename);
	string line;
    // For each line...

	while (getline(input, line)) 
	{    
		istringstream iss(line);    
        // For each character token...    
		if(!(line[0] == '*' || line[0] == '/')){ 
			//if(line.find("st_no:") != string::npos)
				//set_config_map(line);
			if(line.find("conn:") != string::npos)
				set_route_map(line);
			//if(line.find("tr_no:") != string::npos)
				//set_train_config(line);
			if(line.find("train:") != string::npos)
				set_train_plan(line);
		}
	}
	init_trains();
}


void crailway::init_trains(){

	train_iterator iterat_st = m_trainset.begin();

	while(iterat_st != m_trainset.end()){

		iterat_st->second->init_train(this->m_routeplan);
		iterat_st++;
	}
}


void crailway::check_collision(){

	//Now check the collisions
	//each train with other ones
	//double while ()

	//The loop1 -> from 0..N-2
	//    loop2 -> from 1..N-1
	train_iterator tr_it1, tr_it2;
	
	tr_it1 = m_trainset.begin();
	
	while(tr_it1 != --m_trainset.end()){

		tr_it2 = tr_it1;
		tr_it2++;
		while(tr_it2 != m_trainset.end()){

			//Now check the collision
			//tr_it1 with tr_it2
			tr_it1->second->is_collision(tr_it2->second);

			tr_it2++;
		}
		tr_it1++;
	}

}

void crailway::simulate_trains(){

	//This method just execute step by step
	//each train until all of them will be not finished
	bool     end_track = false;
	//int      train_id;
	int      step      = 0;
	ctrain * train;
	train_iterator tr_it; 

	while(!end_track){
		end_track = true;
		step++;
		printf("step:%d----------------\n",step);
		tr_it = m_trainset.begin();
		while(tr_it != m_trainset.end()){

			//train_id = tr_it->first;
			train    = tr_it->second;

			train->make_step();
			end_track = (train->is_finish() && end_track);

			tr_it++;
		}
		
		check_collision();
	}
	if(end_track){

		printf("all trains reach the destination\n");
	}
}
